/***********************************************************************************
 * 文件名： mcu_aes.c
 * 作者： 刘言
 * 版本： 1
 * 说明：
 * 		AES加解密模块驱动。目前仅支持ECB模式， 不支持自动填充。将来考虑支持更多的模式和填充方式。
 * 修改记录：
 * 	2020/8/22: 初版。 刘言。
***********************************************************************************/
#include "HC32_LyLib.h"	
#include "mcu_aes.h"

#if (HC32_MCU_SERIES != HC32F005)

typedef enum _aes_opt
{
    AES_ENCRYPT = 1,
    AES_DECRYPT = 3
}aes_opt;


// 进行一次运转。128bit（16字节）数据。需要确保dat和key至少有16字节的有效数据，否则结果不可
// 预测将无法解密。加密后的数据直接覆盖明文数据。
// 注意：dat或者key指针必须指向可以被4整除的地址处（4字节对齐）否则会引发Hardfault！！！
// dat: 要加密或者解密的数据（前16字节有效）
// key: 密钥（前16字节有效）
// opt: 操作 1-加密，3-解密
static void Operate128b(u32 *dat, u32 opt, const u32 *key)
{
    // 复制密钥
    M0P_AES->KEY0 = key[0];
    M0P_AES->KEY1 = key[1];
    M0P_AES->KEY2 = key[2];
    M0P_AES->KEY3 = key[3];

    // 复制数据
    M0P_AES->DATA0 = dat[0];
    M0P_AES->DATA1 = dat[1];
    M0P_AES->DATA2 = dat[2];
    M0P_AES->DATA3 = dat[3];

    M0P_AES->CR = opt;     // 模式，并开始计算 ！！同时写入2个位待验证
    while(M0P_AES->CR == opt);    // 计算结束

    // 复制数据
    dat[0] = M0P_AES->DATA0;
    dat[1] = M0P_AES->DATA1;
    dat[2] = M0P_AES->DATA2;
    dat[3] = M0P_AES->DATA3;
}

// AES加密，ECB模式。需要确保有效数据长度为16的整数倍(128bits)，否则加密结果不可预测，将无法解密。
// 注意：dat或者key指针必须指向可以被4整除的地址处（4字节对齐）否则会引发Hardfault！！！
void Aes_Encrypt(u8 *dat, int len, const u8 *key)
{
    while (len > 0)
    {
        Operate128b((u32 *)dat, AES_ENCRYPT, (const u32 *)key);
        len -= 16;
    }
}

// AES解密 ECB模式。需要确保有效数据长度为16的整数倍(128bits)，否则解密结果可能错误。
// 注意：dat或者key指针必须指向可以被4整除的地址处（4字节对齐）否则会引发Hardfault！！！
void Aes_Decrypt(u8 *dat, int len, const u8 *key)
{
    while (len > 0)
    {
        Operate128b((u32 *)dat, AES_DECRYPT, (const u32 *)key);
        len -= 16;
        dat += 16;
    }
}

#else
    #error "不支持硬件AES加速的型号"
#endif

